/**
 *
 */
package com.naiterui.ehp.bs.b2c.common.remote;


import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.bo.patient.PatientBO;
import com.naiterui.ehp.bp.bo.recommend.MedicationRecomBO;
import com.naiterui.ehp.bp.bo.recommend.MedicationRecomDetailBO;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bp.utils.net.RestHttpUtil;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.sf.request.SfTraceQueryRequest;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.sf.response.SfTraceLogs;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PlatformRecomCancelParamVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PlatformRecomStatusParamVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PlatformRecomVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PrescriptionPlatformProductVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PrescriptionPlatformResponseVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PrescriptionPlatformTokenVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.PrescriptionRecomStatusVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.ProductInventoryParamVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.ProductInventoryResponseVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.ProductRequestNumberParamVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.ProductRequestTimeParamVO;
import com.naiterui.ehp.bs.b2c.thirdparty.vo.ProductsInventoryParamVO;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@AllArgsConstructor
public class B2cRemoter implements IB2cRemoter {

    private final B2cRemoterConfig b2cRemoterConfig;

    @Override
    public boolean checkDrToken(String doctorId, String token) throws BusinessException {

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("doctorId", doctorId);
        paramMap.put("token", token);

        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getCheckDrToken())
            .paramMap(paramMap)
            .executeData(new ParameterizedTypeReference<ResponseVO<Boolean>>() {
            });
    }

    @Override
    public boolean checkPtToken(String patientId, String token) throws BusinessException {
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("patientId", patientId);
        paramMap.put("token", token);

        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getCheckPtToken())
            .paramMap(paramMap)
            .executeData(new ParameterizedTypeReference<ResponseVO<Boolean>>() {
            });
    }

    @Override
    public MedicationRecomBO getRecomInfo(Long recomId) throws BusinessException {
        Map<String, String> param = new HashMap<>();
        param.put("recomId", recomId + "");
        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getTuijianRecomInfo())
            .paramMap(param)
            .executeData(new ParameterizedTypeReference<ResponseVO<MedicationRecomBO>>() {
            });
    }

    @Override
    public List<MedicationRecomBO> getRecomInfos(List<Long> recomIds) throws BusinessException {
        if (recomIds == null || recomIds.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, String> param = new HashMap<>();
        param.put("recomIds", StringUtil.convertListToStr(recomIds));

        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getTuijianRecomInfoList())
            .paramMap(param)
            .executeData(new ParameterizedTypeReference<ResponseVO<List<MedicationRecomBO>>>() {
            });
    }

    @Override
    public List<MedicationRecomDetailBO> getRecomDetail(Long recomId) throws BusinessException {
        Map<String, String> param = new HashMap<>();
        param.put("recomIds", recomId + "");
        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getTuijianRecomDetail())
            .paramMap(param)
            .executeData(new ParameterizedTypeReference<ResponseVO<List<MedicationRecomDetailBO>>>() {
            });
    }

    @Override
    public PatientBO getPatientInfo(Long patientId) throws BusinessException {
        Map<String, String> param = new HashMap<>();
        param.put("patientId", patientId + "");
        return RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getPatientUserInfo())
            .paramMap(param)
            .executeData(new ParameterizedTypeReference<ResponseVO<PatientBO>>() {
            });
    }

    @Override
    public PrescriptionPlatformTokenVO getPrescriptionPlatformToken() {
        Map<String, String> param = new HashMap<>();
        param.put("client_id", ConfigUtil.getString("prescription.platform.client.id"));
        param.put("client_secret", ConfigUtil.getString("prescription.platform.client.secret"));
        param.put("grant_type", "client_credentials");
        ResponseEntity<PrescriptionPlatformTokenVO> entity = RestHttpUtil.post()
            .url(this.b2cRemoterConfig.getPlatformTokenUrl())
            .paramMap(param)
            .execute(new ParameterizedTypeReference<PrescriptionPlatformTokenVO>() {
            });
        return entity.getBody();
    }

    @Override
    public PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO> getPlatformProduct(String accessToken, String start, String end)
        throws BusinessException {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ProductRequestTimeParamVO param = ProductRequestTimeParamVO.builder().startDate(start).endDate(end).build();
        ResponseEntity<PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO>> entity = RestHttpUtil.post()
            .body(JsonMapper.toJson(param))
            .url(this.b2cRemoterConfig.getPlatformProductUrl())
            .header(header)
            .execute(new ParameterizedTypeReference<PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO>>() {
            });
        PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO> result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return getPlatformProduct(accessToken, start, end);
        }
        return result;
    }

    @Override
    public PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO> getPlatformProduct(String accessToken, String numbers)
        throws BusinessException {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ProductRequestNumberParamVO param = ProductRequestNumberParamVO.builder().drugCode(numbers).build();
        ResponseEntity<PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO>> entity = RestHttpUtil.post()
            .body(JsonMapper.toJson(param))
            .header(header)
            .url(this.b2cRemoterConfig.getPlatformProductUrl())
            .execute(new ParameterizedTypeReference<PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO>>() {
            });
        PrescriptionPlatformResponseVO<PrescriptionPlatformProductVO> result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return getPlatformProduct(accessToken, numbers);
        }
        return result;
    }

    @Override
    public ProductInventoryResponseVO getProductInventory(String accessToken, List<ProductInventoryParamVO> drugList) {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ProductsInventoryParamVO param = ProductsInventoryParamVO.builder().drugList(drugList).build();
        ResponseEntity<ProductInventoryResponseVO> entity = RestHttpUtil.post().body(JsonMapper.toJson(param)).header(header)
            .url(this.b2cRemoterConfig.getPlatformProductInventoryUrl())
            .execute(new ParameterizedTypeReference<ProductInventoryResponseVO>() {
            });
        log.info("获取库存信息参数：{}", JsonMapper.toJson(param));
        log.info("获取库存信息URL：{}", this.b2cRemoterConfig.getPlatformProductInventoryUrl());
        log.info("获取库存信息结果：{}", JsonMapper.toJson(entity.getBody()));
        ProductInventoryResponseVO result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return getProductInventory(accessToken, drugList);
        }
        return result;
    }

    @Override
    public PrescriptionPlatformResponseVO synchroPrescriptionPlatformRecom(String accessToken, PlatformRecomVO platformRecom)
        throws BusinessException {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ResponseEntity<PrescriptionPlatformResponseVO> entity = RestHttpUtil.post().header(header).body(JsonMapper.toJson(platformRecom))
            .url(this.b2cRemoterConfig.getPlatformSynchroRecomUrl())
            .execute(new ParameterizedTypeReference<PrescriptionPlatformResponseVO>() {
            });
        PrescriptionPlatformResponseVO result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return synchroPrescriptionPlatformRecom(accessToken, platformRecom);
        }
        return result;
    }

    @Override
    public PrescriptionPlatformResponseVO calcelPlatformRecom(String accessToken, Long recomId) {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        PlatformRecomCancelParamVO paramVO = PlatformRecomCancelParamVO.builder().recipeId(recomId.toString())
            .sourceId(ConfigUtil.getString("prescription.platform.sourceId")).build();
        ResponseEntity<PrescriptionPlatformResponseVO> entity = RestHttpUtil.post().header(header).body(JsonMapper.toJson(paramVO))
            .url(this.b2cRemoterConfig.getPlatformRecomCancelUrl()).execute(
                new ParameterizedTypeReference<PrescriptionPlatformResponseVO>() {
                });
        PrescriptionPlatformResponseVO result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return calcelPlatformRecom(accessToken, recomId);
        }
        return result;
    }

    @Override
    public PrescriptionPlatformResponseVO<PrescriptionRecomStatusVO> getPrescriptionStatus(String accessToken, PlatformRecomStatusParamVO param) {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ResponseEntity<PrescriptionPlatformResponseVO<PrescriptionRecomStatusVO>> entity = RestHttpUtil.post().header(header)
            .body(JsonMapper.toJson(param))
            .url(this.b2cRemoterConfig.getPlatformRecomStatusUrl()).execute(
                new ParameterizedTypeReference<PrescriptionPlatformResponseVO<PrescriptionRecomStatusVO>>() {
                });
        PrescriptionPlatformResponseVO<PrescriptionRecomStatusVO> result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return getPrescriptionStatus(accessToken, param);
        }
        return result;
    }

    @Override
    public PrescriptionPlatformResponseVO<SfTraceLogs> getLogisticsInfo(String accessToken, SfTraceQueryRequest param) {
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", accessToken);
        ResponseEntity<PrescriptionPlatformResponseVO<SfTraceLogs>> entity = RestHttpUtil.post().header(header)
            .body(JsonMapper.toJson(param))
            .url(this.b2cRemoterConfig.getPlatformRouteInfoUrl()).execute(
                new ParameterizedTypeReference<PrescriptionPlatformResponseVO<SfTraceLogs>>() {
                });
        PrescriptionPlatformResponseVO<SfTraceLogs> result = entity.getBody();
        if (result.getCode().equals("401")) {
            // 刷新accessToken之后重新请求接口
            accessToken = this.referenceAccessToken();
            return getLogisticsInfo(accessToken, param);
        }
        return result;
    }

    public String referenceAccessToken() {
        PrescriptionPlatformTokenVO vo = this.getPrescriptionPlatformToken();
        String token = "bearer " + vo.getAccess_token();
        RedisUtil.keyOps().delete(CommonConstant.RDS_PRESCRIPTION_PLATFORM_TOKEN_KEY);
        RedisUtil.valueOps().set(CommonConstant.RDS_PRESCRIPTION_PLATFORM_TOKEN_KEY, token, 60 * 60);
        return token;
    }
}
